﻿using FluentMigrator;
using FrameworkCore.Modules;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using FrameworkCore.Modules.Startups;
using FluentMigrator.Runner;
using FrameworkCore.Constants;
using FrameworkCore.Migrations;
using Infrastructure.Persistence;
using FrameworkCore.Extensions;

namespace Infrastructure.Startups;

/// <summary>
/// 表示用于在应用程序启动时配置数据库上下文的对象
/// </summary>
public partial class NetModulerDbStartup : INetModulerStartup
{
    /// <summary>
    /// 添加和配置任何中间件
    /// </summary>
    /// <param name="services">服务描述符的集合</param>
    /// <param name="configuration">应用程序的配置</param>
    public void ConfigureServices(IServiceCollection services, IConfiguration configuration)
    {
        // 从配置中获取连接字符串
        var connectionString = configuration.GetConnectionString(GlobalConstants.DefaultConnectionKey)!;

        // 获取数据库类型配置（例如：SQL Server、MySQL、PostgreSQL）
        var dbType = configuration[GlobalConstants.DatabaseTypeKey]!;

        var typeFinder = Singleton<ITypeFinder>.Instance;
        var mAssemblies = typeFinder.FindClassesOfType<MigrationBase>()
            .Select(t => t.Assembly)
            .Where(assembly => !assembly.FullName!.Contains("FluentMigrator.Runner"))
            .Distinct()
            .ToArray();

        // 数据库迁移配置
        services
            .AddFluentMigratorCore()
            .ConfigureRunner(rb =>
            {
                switch (dbType.ToLower())
                {
                    case DbProviderKeys.SqlServer:
                        rb.AddSqlServer();
                        break;
                    case DbProviderKeys.Mysql:
                        rb.AddMySql8();
                        break;
                    case DbProviderKeys.Npgsql:
                        rb.AddPostgres();
                        break;
                    case DbProviderKeys.SqLite:
                        rb.AddSQLite();
                        break;
                    default:
                        throw new Exception("不支持的数据库类型");
                }

                rb.WithGlobalConnectionString(connectionString)
                  .ScanIn(mAssemblies).For.Migrations();
            });

       services.AddDbContextService(configuration);

        // 数据库提供者
        switch (dbType.ToLower())
        {
            case DbProviderKeys.SqlServer:
                services.AddScoped<INetModulerDataProvider, SqlServerDataProvider>();
                break;
            case DbProviderKeys.Mysql:
                services.AddScoped<INetModulerDataProvider, MySqlDataProvider>();
                break;
            case DbProviderKeys.Npgsql:
                services.AddScoped<INetModulerDataProvider, PostgreSqlDataProvider>();
                break;
            case DbProviderKeys.SqLite:
                services.AddScoped<INetModulerDataProvider, SqliteDataProvider>();
                break;
            default:
                throw new Exception("不支持的数据库类型");
        }

        // 仓储
        // services.AddScoped(typeof(IRepository<>), typeof(Repository<>));

        // 如果数据库不存在则创建，并且执行迁移
        using (var scope = services.BuildServiceProvider().CreateScope())
        {
            var dataProvider = scope.ServiceProvider.GetRequiredService<INetModulerDataProvider>();
            dataProvider.CreateDatabaseIfNotExists(connectionString);

            var runner = scope.ServiceProvider.GetRequiredService<IMigrationRunner>();
            try
            {
                runner.MigrateUp();
                Console.WriteLine($"完成迁移");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"迁移：{ex.Message}");
            }
        }
    }

    /// <summary>
    /// 配置已添加中间件的使用
    /// </summary>
    /// <param name="application">用于配置应用程序请求管道的生成器</param>
    public void Configure(IApplicationBuilder application)
    {
    }

    /// <summary>
    /// 获取此启动配置实现的顺序
    /// </summary>
    public int Order => 10;
}